package org.bing.engine.common.graniteds;

import javax.servlet.ServletContext;

import org.bing.engine.common.logging.Log;
import org.bing.engine.common.logging.LogFactory;
import org.granite.context.GraniteContext;
import org.granite.messaging.service.DefaultMethodMatcher;
import org.granite.messaging.service.ServiceException;
import org.granite.messaging.service.ServiceInvocationContext;
import org.granite.messaging.webapp.HttpGraniteContext;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;


import flex.messaging.messages.RemotingMessage;

public class AMF3MessageSpringInvoker {
	private static final Log logger = LogFactory.getLog(AMF3MessageSpringInvoker.class);
	private static final ApplicationContext springContext;
	private static final DefaultMethodMatcher methodMatcher = new DefaultMethodMatcher();

	static {
		GraniteContext context = GraniteContext.getCurrentInstance();
		ServletContext sc = ((HttpGraniteContext) context).getServletContext();
		springContext = WebApplicationContextUtils.getRequiredWebApplicationContext(sc);
	}

	public static Object invoke(RemotingMessage request) {
		Object service = findSpringBean(request);
		String methodName = request.getOperation();
		Object[] params = (Object[]) request.getBody();
		try {
			ServiceInvocationContext context = methodMatcher.findServiceMethod(request, null, service, methodName,
					params);
			Object result = context.invoke();
			return result;
		} catch (Exception e) {
			throw new ServiceException("Fail to process amf request! ", e);
		}
	}

	private static Object findSpringBean(RemotingMessage request) {
		String destinationId = request.getDestination();
		Object obj = springContext.getBean(destinationId);
		if (obj == null) {
			logger.error("Can't find bean by amf's destination " + destinationId);
		}
		return obj;
	}

}
